PRG 1.0 TXT

/*
	Directional Light
*/

//-----------------------------------------------------------------------------
// [CONFIG]

include "..\program_include.ocf"

object Program
{
	type		= e_program.DIFFUSE;
	layer_bits	= e_render_layer_bits.ALL;
	
	ubo_data	= array /*UBO*/ {
		{ "inLight", 	 e_program_data.LIGHT }
	}

	textures	= array /*ProgramTexture*/ {
		{ "unDNNS",		 e_texture.DIFFUSE },
		{ "unRGBM",		 e_texture.DIFFUSE },
		{ "unDepthMap",  e_texture.DIFFUSE },
		{ "unShadow", 	 e_texture.SHADOW }
	}
	
	uniforms	= array /*string*/ {
		"transform", "unTransform."
	}
}


//-----------------------------------------------------------------------------
// [VERTEX]

#version 330 core
#pragma optimize(on)

#define ATTR_POSITION	0
#define ATTR_NORMAL		1
#define ATTR_TEXCOORD	2

layout(location = ATTR_POSITION) in vec3  inPosition;

uniform struct TTransform {
	mat4	MVP;
	mat4	ProjectionInverse;
} unTransform;

out	TVertexData {
	vec3	vPos;
} Output;


void main()
{
	gl_Position = unTransform.MVP * vec4(inPosition, 1.0);
	Output.vPos = gl_Position.xyz / gl_Position.w;
}


//-----------------------------------------------------------------------------
// [FRAGMENT]

#version 330 core
#pragma optimize(on)

#define color_t		vec3
#define	E			2.7182818
#define PI			3.1415926
#define EPSILON		0.00001

layout(location = 0, index = 0)	out vec4  outColor;

uniform struct TTransform {
	mat4	VP;
	mat4	ProjectionInverse;
} unTransform;

uniform sampler2D			unDNNS;
uniform sampler2D			unRGBM;
uniform sampler2D			unDepthMap;
uniform samplerCubeShadow	unShadow;

vec2						vTexcoord;

layout(std140)
uniform inLight {
	mat4	mTransform[6];
	vec3	vLightPos;
	vec3	vDiffuse;
	vec3	vSpecular;
	vec3	vAtten;
	float	fRadius;
} unLight;

in	TVertexData {
	vec3	vPos;
} Input;


vec3 UnpackMVpos()
{
	float	depth	= texture( unDepthMap, vTexcoord ).r * 2.0 - 1.0;
	vec4	pos		= unTransform.ProjectionInverse * vec4( Input.vPos.xy, depth, 1.0 );
	return pos.xyz / pos.w;
}


vec3 GetInputNormal(vec2 vNormal)
{ 
	vec3	res;
	res.xy = ( abs(vNormal) * 2.0 ) - 1.0;
	res.z  = ( vNormal.x < 0.0 ? -1.0 : 1.0 ) * sqrt( abs( 1.0 - res.x*res.x - res.y*res.y ) );
	return res;
}


void CookTorrance(out color_t vDiffOut, out color_t vSpecOut, in color_t vDiffuse, in color_t vSpecular,
			in vec3 vLightDir, in vec3 vViewDir, in vec3 vNormal, in vec3 vH, in float r0, in float roughness)
{
	float	nh	= dot( vNormal, vH );
	float	nv	= dot( vNormal, vViewDir );
	float	nl	= dot( vNormal, vLightDir );
	float	r2	= roughness * roughness;
	float	nh2	= nh * nh;
	float	ex	= - (1.0 - nh2) / (nh2 * r2);
	float	d	= pow( E, ex ) / (r2 * nh2 * nh2);
	float	f	= mix( pow( 1.0 - nv, 5.0 ), 1.0, r0 );
	float	x	= 2.0 * nh / dot( vViewDir, vH );
	float	g	= min( 1.0, min( x * nl, x * nv ) );
	float	ct	= d*f*g / nv;
	vDiffOut	= vDiffuse * max( 0.0, nl );
	vSpecOut	= vSpecular * max( 0.0, ct );
}


float Attenuation(in vec3 vAtten, in float fDist)
{
	return 1.0 / ( vAtten.x + vAtten.y * fDist + vAtten.z * fDist * fDist );
}


vec3 Lighting(in vec3 vNormal, in vec3 vViewDir, in vec3 vLightDir, vec3 vDiffuse,
				in vec3 vSpecular, float fShininess, float fMaterial)
{
	vec3	diff;
	vec3	spec;
	vec3	h	= normalize( vLightDir + vViewDir );

	CookTorrance( diff, spec, vDiffuse, vSpecular, vLightDir, vViewDir, vNormal, h, fShininess, fMaterial );
	return diff + spec;
}


float Shading(in vec3 vPos)
{
	// TODO: choose cube face
	vec4	coord = unLight.mTransform[0] * vec4( vPos, 1.0 );
	return textureProj( unShadow, coord );
}


void main()
{
	vTexcoord			= Input.vPos.xy * 0.5 + 0.5;
	vec3	pos			= UnpackMVpos();
	float	dist		= distance( Input.vLightPos, pos );
	float	atten		= Attenuation( Input.vAtten, dist );
	float	shadow		= Shading( pos ) * atten;
	
	if ( dist > Input.fRadius || shadow < EPSILON )
		discard;
		
	vec4	vDNNS		= texture( unDNNS, Input.vTexcoord );
	vec3	normal		= GetInputNormal( vDNNS.gb );
	vec3	light_dir	= normalize( Input.vLightPos - pos );
	float	shininess	= vDNNS.a;
	float	material	= texture( unRGBM, Input.vTexcoord ).a;
	int		data_size	= textureSize( unLightData );
	vec3	view_dir	= normalize( -pos );

	outColor.a	 = 1.0;
	outColor.rgb = Lighting( normal, view_dir, light_dir, Input.vDiffuse,
							Input.vSpecular, shininess, material ) * shadow;
}

// [END]
